package controllers

import (
	"net/http"
	"rego-top/dto"
	"rego-top/middleware"
	"rego-top/services"

	"github.com/gin-gonic/gin"
)

type AuthController struct {
	userService  *services.UserService
	emailService *services.EmailService
}

// NewAuthController 创建认证控制器实例
func NewAuthController() *AuthController {
	return &AuthController{
		userService:  services.NewUserService(),
		emailService: services.NewEmailService(),
	}
}

// Register 用户注册
func (ac *AuthController) Register(c *gin.Context) {
	data, exists := middleware.GetValidatedData(c)
	if !exists {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("参数验证失败", nil))
		return
	}

	req := data.(*dto.RegisterRequest)

	user, err := ac.userService.Register(*req)
	if err != nil {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("注册失败", err.Error()))
		return
	}

	// 发送验证邮件
	if err := ac.emailService.SendVerificationEmail(user.Email, user.EmailVerificationToken); err != nil {
		// 邮件发送失败不影响注册成功，只记录错误
		// 在生产环境中应该记录到日志系统
	}

	c.JSON(http.StatusCreated, dto.SuccessResponse("注册成功，请查收验证邮件", map[string]interface{}{
		"user_id": user.ID,
		"email":   user.Email,
	}))
}

// Login 用户登录
func (ac *AuthController) Login(c *gin.Context) {
	data, exists := middleware.GetValidatedData(c)
	if !exists {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("参数验证失败", nil))
		return
	}

	req := data.(*dto.LoginRequest)

	authResponse, err := ac.userService.Login(*req)
	if err != nil {
		c.JSON(http.StatusUnauthorized, dto.ErrorResponse("登录失败", err.Error()))
		return
	}

	c.JSON(http.StatusOK, dto.SuccessResponse("登录成功", authResponse))
}

// RefreshToken 刷新访问令牌
func (ac *AuthController) RefreshToken(c *gin.Context) {
	data, exists := middleware.GetValidatedData(c)
	if !exists {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("参数验证失败", nil))
		return
	}

	req := data.(*dto.RefreshTokenRequest)

	authResponse, err := ac.userService.RefreshToken(*req)
	if err != nil {
		c.JSON(http.StatusUnauthorized, dto.ErrorResponse("令牌刷新失败", err.Error()))
		return
	}

	c.JSON(http.StatusOK, dto.SuccessResponse("令牌刷新成功", authResponse))
}

// GetProfile 获取用户资料
func (ac *AuthController) GetProfile(c *gin.Context) {
	user, exists := middleware.GetCurrentUser(c)
	if !exists {
		c.JSON(http.StatusUnauthorized, dto.ErrorResponse("未认证", nil))
		return
	}

	userInfo := ac.userService.BuildUserInfo(user)
	c.JSON(http.StatusOK, dto.SuccessResponse("获取用户资料成功", userInfo))
}

// VerifyEmail 验证邮箱
func (ac *AuthController) VerifyEmail(c *gin.Context) {
	token := c.Query("token")
	if token == "" {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("缺少验证令牌", nil))
		return
	}

	if err := ac.userService.VerifyEmail(token); err != nil {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("邮箱验证失败", err.Error()))
		return
	}

	c.JSON(http.StatusOK, dto.SuccessResponse("邮箱验证成功", nil))
}

// ResendVerificationEmail 重新发送验证邮件
func (ac *AuthController) ResendVerificationEmail(c *gin.Context) {
	email := c.Query("email")
	if email == "" {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("缺少邮箱参数", nil))
		return
	}

	if err := ac.emailService.ResendVerificationEmail(email); err != nil {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("发送验证邮件失败", err.Error()))
		return
	}

	c.JSON(http.StatusOK, dto.SuccessResponse("验证邮件已发送", nil))
}

// ForgotPassword 忘记密码
func (ac *AuthController) ForgotPassword(c *gin.Context) {
	data, exists := middleware.GetValidatedData(c)
	if !exists {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("参数验证失败", nil))
		return
	}

	req := data.(*dto.ForgotPasswordRequest)

	if err := ac.emailService.ForgotPassword(*req); err != nil {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("发送重置邮件失败", err.Error()))
		return
	}

	c.JSON(http.StatusOK, dto.SuccessResponse("密码重置邮件已发送", nil))
}

// ResetPassword 重置密码
func (ac *AuthController) ResetPassword(c *gin.Context) {
	data, exists := middleware.GetValidatedData(c)
	if !exists {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("参数验证失败", nil))
		return
	}

	req := data.(*dto.ResetPasswordRequest)

	if err := ac.emailService.ResetPassword(*req); err != nil {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("密码重置失败", err.Error()))
		return
	}

	c.JSON(http.StatusOK, dto.SuccessResponse("密码重置成功", nil))
}

// ChangePassword 修改密码
func (ac *AuthController) ChangePassword(c *gin.Context) {
	userID, exists := middleware.GetCurrentUserID(c)
	if !exists {
		c.JSON(http.StatusUnauthorized, dto.ErrorResponse("未认证", nil))
		return
	}

	data, exists := middleware.GetValidatedData(c)
	if !exists {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("参数验证失败", nil))
		return
	}

	req := data.(*dto.ChangePasswordRequest)

	if err := ac.userService.ChangePassword(userID, *req); err != nil {
		c.JSON(http.StatusBadRequest, dto.ErrorResponse("修改密码失败", err.Error()))
		return
	}

	c.JSON(http.StatusOK, dto.SuccessResponse("密码修改成功", nil))
}

// Logout 用户登出
func (ac *AuthController) Logout(c *gin.Context) {
	// 在实际应用中，这里可以将令牌加入黑名单
	// 或者从Redis中删除令牌等操作
	c.JSON(http.StatusOK, dto.SuccessResponse("登出成功", nil))
}